package com.eastedu.template.util;

import com.deepoove.poi.data.ChartMultiSeriesRenderData;
import com.deepoove.poi.data.SeriesRenderData;
import com.eastedu.common.enums.SubjectType;
import com.eastedu.report.common.util.PatternUtil;
import com.eastedu.template.chart.ChartFunction;
import com.eastedu.template.chart.ChartMetadata;
import com.eastedu.template.model.ChartData;
import com.eastedu.template.model.ReportData;
import com.eastedu.template.model.SeriesData;

import java.util.*;
import java.util.stream.Collectors;

/**
 * The interface Chart data util.
 *
 * @author superman
 */
public interface ChartDataUtil {

    /**
     * 根据category和series数据生成图表数据, 如果对应category和series没有数据则填充null
     *
     * @param <T>          the type parameter
     * @param dataFunction 获取数据的函数
     * @return the chart multi series render data
     */
    static <T extends ReportData> ChartFunction<Map<String, Map<String, T>>> charFunction(java.util.function.Function<T, Number> dataFunction) {
        return (categories, series, data) ->
                series.stream()
                        .map(seriesMetadata -> {
                            Map<String, T> seriesData = data.get(seriesMetadata.getCode());
                            return Optional.ofNullable(seriesData).map(value -> {
                                        Number[] serials = categories.stream()
                                                .map(category -> {
                                                    T reportData = seriesData.get(category.getCode());
                                                    return Optional.ofNullable(reportData).map(dataFunction).orElse(null);
                                                }).toArray(Number[]::new);
                                        return new SeriesData(seriesMetadata.getName(), seriesMetadata.getOrder(), serials, SeriesRenderData.ComboType.BAR);
                                    })
                                    .orElseGet(() -> {
                                        Number[] serials = new Number[categories.size()];
                                        return new SeriesData(seriesMetadata.getName(), seriesMetadata.getOrder(), serials, SeriesRenderData.ComboType.BAR);
                                    });
                        })
                        .collect(Collectors.toList());
    }

    /**
     * 转换学届为图表元数据，包括学届名称，学届code，学届排序
     *
     * @param schoolPeriods the school periods
     * @param comparator    the comparator
     * @return the list
     */
    static List<ChartMetadata> convertPeriod(List<String> schoolPeriods, Comparator<ChartMetadata> comparator) {
        return schoolPeriods.parallelStream()
                .map(period ->
                             ChartMetadata.builder()
                                     .name(period)
                                     .code(period)
                                     .order(PatternUtil.extractNumberInteger(period.substring(1, 5)))
                                     .build()
                )
                .sorted(comparator)
                .collect(Collectors.toList());

    }

    /**
     * 转换学科为图表元数据，包括学科名称，学科code，学科排序
     *
     * @param subjects the subjects
     * @return the list
     */
    static List<ChartMetadata> convertSubject(List<String> subjects) {
        return subjects.parallelStream()
                .map(subject -> {
                         SubjectType subjectType = SubjectType.getByCode(subject);
                         return ChartMetadata.builder()
                                 .name(subjectType.getName())
                                 .code(subjectType.getCode())
                                 .order(subjectType.ordinal())
                                 .build();
                     }
                )
                .sorted(Comparator.comparingInt(ChartMetadata::getOrder))
                .collect(Collectors.toList());

    }


    /**
     * 转换图表数据
     *
     * @param chartData the chart data
     * @return the chart multi series render data
     */
    static ChartMultiSeriesRenderData convertChartData(ChartData chartData) {
        ChartMultiSeriesRenderData multiSeriesRenderData = new ChartMultiSeriesRenderData();
        List<SeriesRenderData> renderDataList = new ArrayList<>();
        multiSeriesRenderData.setChartTitle(chartData.getName());
        multiSeriesRenderData.setCategories(chartData.getSeriesCategories());
        for (SeriesData seriesData : chartData.getSeriesDataList()) {
            SeriesRenderData seriesRenderData = new SeriesRenderData(seriesData.getName(), seriesData.getSeriesValue());
            seriesRenderData.setComboType(seriesData.getComboType());
            renderDataList.add(seriesRenderData);
        }
        multiSeriesRenderData.setSeriesDatas(renderDataList);
        return multiSeriesRenderData;
    }
}
